import { miniProgramEnv, server } from '../config'
import { token } from '../user'

/** 请求参数 */
type I_RequestOptions = {
  /** 路径前缀 */
  base?: string
  /** 路径 */
  url?: string
  /** 文件本地列表 */
  files?: {
    /** multipart 提交时，表单的项目名，默认为 file */
    name: string
    /** 文件的本地地址 */
    uri: string
  }[]
  /** 方法 */
  method?: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'
  /** 数据 */
  data?: any

  /** 是否不需要携带token */
  noToken?: boolean

  [key: string]: any
}

/** 基础响应数据 */
type I_BaseResponse<T> = {
  /** 0为正常，message为空字符串;其他数值为异常，message返回对应异常信息 */
  code: number
  /** 报错信息 */
  message: string
  /** 数据 */
  data: T
}

const { appVersion } = uni.getSystemInfoSync()

let version = appVersion
let client = ''

// #ifdef WEB
client = 'web'
// #endif

// #ifdef MP
version = miniProgramEnv.version || miniProgramEnv.env
client = 'mini'
// #endif

// #ifdef APP
client = 'app'
// #endif

// log(['请求头', { version, client }])

/**
 * 注入公共参数
 * @param options 参数
 */
const getHeader = (options: I_RequestOptions = {}) => {
  const data: { [key: string]: string } = options.header || {}

  delete options.header

  if (options.noToken) delete options.noToken
  else data.auth = token.value

  data.version = version
  data.client = client

  return data
}

/**
 * 请求
 * @param options 请求参数
 */
const request = <T = any>(options: I_RequestOptions = {}) =>
  new Promise<I_BaseResponse<T>>((resolve, reject) => {
    const data = options.data
    const base = options.base !== undefined ? options.base : server.apiServer
    const url = base + (options.url || '')
    const method = options.method || 'GET'
    const header = getHeader(options)

    delete options.base
    delete options.url
    delete options.method

    uni.request({
      ...options,
      url,
      method,
      data,
      header,
      success(res: any) {
        if (typeof res.data === 'object') {
          if (res.data.code === 0) resolve(res.data)
          else reject(res.data)
        } else if (res.statusCode === 200) resolve(res.data)
        else reject(res)
      },
      fail: reject,
    })
  })

/**
 * POST请求
 * @param options 请求参数
 */
const get = <T = any>(url: string, data: any = {}, options: I_RequestOptions = {}) => {
  options.method = 'GET'
  options.url = url
  options.data = data

  return request<T>(options)
}

/**
 * POST请求
 * @param url 路径
 * @param data 数据
 * @param options 参数
 */
const post = <T = any>(url: string, data?: any, options: I_RequestOptions = {}) => {
  options.method = 'POST'
  options.url = url
  options.data = data

  return request<T>(options)
}

// #ifdef MP
// import { FormData } from './mp-formData'
// #endif

/**
 * 上传文件
 * @param options 请求参数
 */
const upload = <T = any>(options: I_RequestOptions = {}) =>
  new Promise<I_BaseResponse<T>>((resolve, reject) => {
    const data = options.data
    const base = options.base !== undefined ? options.base : server.apiServer
    const url = base + (options.url || '')
    const method = options.method || 'POST'
    const header = getHeader(options)
    const files = options.files || []

    delete options.base
    delete options.url
    delete options.method
    delete options.files

    // #ifdef WEB || APP || MP
    let _files = []
    for (const key in files) {
      _files.push({
        uri: files[key].uri,
        name: 'file' + (parseInt(key) + 1),
      })
    }

    const task = uni.uploadFile({
      ...options,
      url,
      method,
      files: _files,
      formData: data,
      header,
      success(res: any) {
        if (typeof res.data === 'string') {
          try {
            res.data = JSON.parse(res.data)
          } catch (err) {}
        }

        if (typeof res.data === 'object') {
          if (res.data.code === 0) resolve(res.data)
          else reject(res.data)
        } else if (res.statusCode === 200) resolve(res.data)
        else reject(res)
      },
      fail: err => reject(err),
    })

    task.onProgressUpdate(res => {
      options.onProgress?.(res.progress)
    })
    // #endif

    // #ifdef MP
    // const formData = new FormData()

    // // for (const file of files) {
    // //   formData.appendFile('file', file.uri, file.name)
    // // }

    // options.filePath &&
    //   options.name &&
    //   formData.appendFile(options.name, options.filePath, options.name)

    // for (const key in files) {
    //   formData.appendFile('file' + (parseInt(key) + 1), files[key].uri, files[key].name)
    // }

    // for (const key in data) {
    //   formData.append(key, data[key])
    // }

    // const _formData = formData.getData()

    // uni.request({
    //   ...options,
    //   url,
    //   method,
    //   files,
    //   header: { 'content-type': _formData.contentType },
    //   data: _formData.buffer,
    //   success(res: any) {
    //     if (res.data && typeof res.data === 'object') {
    //       if (res.data.code === 0) resolve(res.data)
    //       else reject(res.data)
    //     } else if (res.statusCode === 200) resolve(res.data)
    //     else reject(res)
    //   },
    //   fail: reject,
    // })
    // #endif
  })

/**
 * 获取JSON
 * @param base JSON资源地址
 * @param options 参数
 */
const getJSON = <T = any>(base: string, options: I_RequestOptions = {}) =>
  request<T>({ base, ...options })

export { request, get, post, upload, getJSON }

export * from './report'
